package com.sservice.service.service.impl;

import com.sservice.common.Constants;
import com.sservice.model.dao.*;
import com.sservice.model.entity.*;
import com.sservice.model.log.BillType;
import com.sservice.model.vo.LadingBillVo;
import com.sservice.model.vo.LadingOrderVo;
import com.sservice.service.service.*;
import com.sservice.urp.entity.Permission;
import com.sservice.urp.vo.UserVo;
import com.sservice.web.common.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by suweiming on 2017/12/20.
 */

@Service
@Transactional
public class LadingBillServiceImpl implements ILadingBillService {
    @Autowired
    private ILadingBillDao dataDao;
    @Autowired
    private IOrderDao orderDao;
    @Autowired
    private IStoreDao storeDao;
    @Autowired
    private IOfferDao offerDao;
    @Autowired
    private IGoodsDao goodsDao;
    @Autowired
    private LadingOrderMapper ladingOrderDao;
    @Autowired
    private ISaleCommissionDao saleCommissionDao;
    @Autowired
    private ISaleCommissionService saleCommissionService;
    @Autowired
    private ISalePersonAccountDao spaDao;
    @Autowired
    private ISalePersonAccountService spaService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private BillBillMapper bbDao;
    @Autowired
    private PurchaseOrderBillMapper pobDao;
    @Autowired
    private PurchaseOrderBillService pobService;
    @Autowired
    private PurchaseOrderMapper poDao;
    @Autowired
    private ILadingBillLogService lblService;
    @Autowired
    private IOrderAdvanceReceiptService iOrderAdvanceReceiptService;

    @Override
    public int deleteByPrimaryKey(Integer id) {
        return dataDao.deleteByPrimaryKey(id);
    }

    @Override
    public int insert(LadingBill record) {
        record.setNo(Constants.generateServiceNO("T", Constants.generateLimitNumberStr(getMaxInNoOrder() + 1, 4)));
        return dataDao.insert(record);
    }

    @Override
    public int insertSelective(LadingBill record) {
        record.setNo(Constants.generateServiceNO("T", Constants.generateLimitNumberStr(getMaxInNoOrder() + 1, 4)));
        return dataDao.insertSelective(record);
    }

    /**
     * 授权账户发货
     *
     * @param record
     * @return
     */
    @Transactional
    @Override
    public Object permissionCreate(LadingBillVo record) {
        record.setNo(Constants.generateServiceNO("T", Constants.generateLimitNumberStr(dataDao.queryCurrentDayCount() + 1, 4)));
        record.setActual(BigDecimal.ZERO);
        String[] orderId = record.getOrderIds().split(",");
        String[] numbers = record.getOrderNumbers().split(",");
        Order order_ = orderDao.selectByPrimaryKey(Integer.valueOf(orderId[0]));
        record.setNumberThisTime(ArrayUtils.strArrayTotal(numbers));
        record = initLadingBillVo(order_, record);
        dataDao.insertSelective(record);
        for (int i = 0; i < orderId.length; i++) {
            Order order = orderService.selectByPrimaryKey(Integer.valueOf(orderId[i]));
            LadingOrder lo = generateLadingOrder(
                    orderId[i],
                    numbers[i],
                    record.getId(),
                    record.getNo(),
                    order.getActualPrice(),
                    order.getQuality());
            ladingOrderDao.insertSelective(lo);
            orderService.changeNumber(
                    order.getId(),
                    BigDecimal.valueOf(Double.valueOf(numbers[i])),
                    BigDecimal.ZERO
            );
        }
        return null;

    }

    public LadingBillVo initLadingBillVo(Order order_, LadingBillVo record) {
        record.setSaler(order_.getSaleName()); // 操作员
        record.setClienteleName(order_.getClienteleName());
        record.setClienteleId(order_.getClienteleId());
        record.setSaler(order_.getSaleName()); // 操作员
        record.setUnitCode(order_.getUnitCode());
        record.setGoodsName(order_.getGoodsName());
        record.setGoodsId(order_.getGoodsId());
        record.setGoodsNo(order_.getGoodsNo());
        record.setPrice(order_.getActualPrice()); // 先行单价
        record.setQualityRequire(order_.getQualityRequire());// 质量标准
        record.setQuality(order_.getQuality());//品质规格
        record.setPack(order_.getPack());
        return record;
    }

    /**
     * 初始化 Lading Order
     */
    public LadingOrder generateLadingOrder(String orderId, String number, int ladingId, String no, BigDecimal price, String quality) {
        LadingOrder lo = new LadingOrder();
        lo.setNumber(BigDecimal.valueOf(Double.valueOf(number)));
        lo.setOrderId(orderId);
        lo.setLadingId(String.valueOf(ladingId)); //
        lo.setLadingNo(no);
//        lo.setBillId(ladingId);
        lo.setBillBatch(null);
        lo.setPrice(price);
        lo.setQuality(quality);
        return lo;
    }

    /***
     * 创建提货订单：此方法只为后台用户创建提单使用
     * @param record 提单日志
     * @param isForce  是否强制执行完毕 true:是, false ：不是
     * @return
     */
    @Override
    public Object create(LadingBillVo record, Boolean isForce) {
        return 0;
    }

    /**
     * @param record
     * @param isForce
     * @return
     */
    @Override
    public Object allow(LadingBillVo record, Boolean isForce) {
        String[] ladingOrderIds = record.getOrderIds().split(",");
        String[] billIds = record.getBillIds().split(",");
        String[] batches = record.getBatchNum().split(",");
        PurchaseOrderBill order = null;
        for (int i = 0; i < ladingOrderIds.length; i++) {
            LadingOrder lo = ladingOrderDao.selectByPrimaryKey(Integer.valueOf(ladingOrderIds[i]));
            lo.setBillId(billIds[i]);
            lo.setBillBatch(batches[i]);
            pobService.changeNumber(
                    Integer.valueOf(billIds[i]),
                    BigDecimal.ZERO,
                    BigDecimal.ZERO,
                    lo.getNumber(),
                    null
            );
            ladingOrderDao.updateByPrimaryKeySelective(lo); //
        }

        PurchaseOrderBill pob = pobDao.selectByPrimaryKey(Integer.valueOf(billIds[0]));
        record.setStoreId(pob.getStoreId());
        record.setStoreName(pob.getStoreName());//
        record.setCheckStatus("1"); // 审核通过
        return dataDao.updateByPrimaryKeySelective(record);
    }

    /***
     *  审核拒绝
     * @param record
     * @return
     */
    @Transactional
    @Override
    public Object refuse(LadingBillVo record) {
        LadingBill lb = dataDao.selectByPrimaryKey(record.getId());
        if (lb == null) return "参数错误";
        if (!"0".equals(lb.getCheckStatus())) return "参数错误";

        List<LadingOrder> list = ladingOrderDao.selectByLadingId(String.valueOf(record.getId()));
        for (LadingOrder lo : list) {
            orderService.changeNumber(
                    Integer.valueOf(lo.getOrderId()),
                    lo.getNumber().negate(),
                    BigDecimal.ZERO
            );
        }
        record.setCheckStatus("2");// 审核拒绝
        record.setReason(record.getReason());
        return dataDao.updateByPrimaryKeySelective(record);
    }

    public Object send(LadingBillVo record, String isSuper) {
        if (record.getBillIds() == null || "".equals(record.getBillIds())) {
            return "请选择批号发货!";
        }
        if (BillType.CAR_ID.getIndex().equals(record.getType())) {
            String[] billIds = record.getBillIds().split(",");
            if (billIds.length != 1) {
                System.out.println("车号类型发货单，只能选择一个收货批号");
            }
        }
        record.setNo(Constants.generateServiceNO("T", Constants.generateLimitNumberStr(getMaxInNoOrder() + 1, 4)));
        String orderId = record.getOrderIds().split(",")[0];
        String[] prices = record.getPrices().split(","); //
        String[] qualitys = record.getQuality().split(",");
        Order order_ = orderDao.selectByPrimaryKey(Integer.valueOf(orderId));
        if (order_.getPayStatus().equals("0")) {
            if ("0".equals(isSuper)) {
                return "销售订单未付款，不能发货!";
            }
        } else if ("2".equals(order_.getPayStatus())) {
            if ("0".equals(isSuper)) {
                BigDecimal total = record.getNumberThisTime().add(order_.getDeliverNumber());
                total = total.multiply(order_.getActualPrice());
                if (total.compareTo(order_.getActualReceived()) == 1) {
                    return "订单付款累计不足发货所用货款!";
                }
            }
        }
        record.setClienteleName(order_.getClienteleName());
        record.setClienteleId(order_.getClienteleId());
        record.setSaler(order_.getSaleName()); // 操作员
        record.setUnitCode(order_.getUnitCode());
        record.setGoodsName(order_.getGoodsName());
        record.setGoodsId(order_.getGoodsId());
        record.setGoodsNo(order_.getGoodsNo());
        record.setQuality(order_.getQuality());
        record.setPrice(order_.getActualPrice()); // 先行单价
        record.setQualityRequire(order_.getQualityRequire());
        record.setPack(order_.getPack());
        dataDao.insertSelective(record); //创建提货单
        String[] orders = record.getOrderIds().split(",");
        String[] numbers = record.getOrderNumbers().split(",");
        String[] billIds = record.getBillIds().split(",");
        String[] batchIds = record.getBatchNum().split(",");
        List list = new ArrayList();
        Map<String, Order> ordersMap = new HashMap<String, Order>();
        Map<String, PurchaseOrderBill> billsMap = new HashMap<String, PurchaseOrderBill>();
//        System.out.println("发货：====》" + numbers.toString());
        for (int i = 0; i < orders.length; i++) {
            LadingOrder lo = new LadingOrder();
            lo.setNumber(BigDecimal.valueOf(Double.valueOf(numbers[i])));
            lo.setOrderId(orders[i]);
            lo.setLadingId(String.valueOf(record.getId())); //
            lo.setLadingNo(record.getNo());
            lo.setBillId(billIds[i]);
            lo.setBillBatch(batchIds[i]);
            lo.setPrice(BigDecimal.valueOf(Double.valueOf(prices[i])));
            lo.setQuality(qualitys[i]);
            Order order = ordersMap.get(lo.getOrderId());
            if (order == null) {
                order = new Order();
                order.setNumber(new BigDecimal(0.0));
                order.setId(Integer.valueOf(lo.getOrderId()));
            }
            order.setNumber(lo.getNumber().add(order.getNumber()));
            ordersMap.put(lo.getOrderId(), order);
            PurchaseOrderBill pob = billsMap.get(lo.getBillId());
            if (pob == null) {
                pob = new PurchaseOrderBill();
                pob.setId(Integer.valueOf(lo.getBillId()));
                pob.setNumber(new BigDecimal(0.0));
            }
            pob.setNumber(pob.getNumber().add(lo.getNumber()));
            billsMap.put(lo.getBillId(), pob);
            list.add(lo);
        }
        String businessId = "-";
        int ladingOrders = ladingOrderDao.addBatch(list), pointer = 0;
        if (ladingOrders > 0) {
            for (String in : ordersMap.keySet()) {
                Order order = ordersMap.get(in);//得到每个key多对用value的值
                Order order1 = orderService.selectByPrimaryKey(order.getId());
                businessId += (order1.getBusinessId() + "-");
                order.setDeliverNumber(order1.getDeliverNumber().add(order.getNumber()));
                order.setNumber(null);
                orderService.updateByPrimaryKeySelective(order);
            }
            for (String in : billsMap.keySet()) {
                PurchaseOrderBill bill = billsMap.get(in);//得到每个key多对用value的值
                PurchaseOrderBill bill1 = pobDao.selectByPrimaryKey(bill.getId());
                bill.setNumberSending(bill1.getNumberSending().add(bill.getNumber()));
                if (BillType.CAR_ID.getIndex().equals(bill1.getType())) { // 车号类型收货单车号回填
                    bill.setCom(record.getCarId());
                }
                bill.setNumber(null);
                if ("0".equals(bill1.getType()) || "2".equals(bill1.getType())) { // 车号 、 介绍信
                    if (bill1.getNumber().compareTo(bill1.getNumberSended().add(bill.getNumberSending())) == -1) {
                        throw new RuntimeException("提货数量超出收货单数量");
                    }
                } else { // 转货权
                    if (bill1.getNumberReceive().compareTo(bill1.getNumberSended().add(bill.getNumberSending())) == -1) {
                        throw new RuntimeException("提货数量超出收货单实际收货数量");
                    }
                }
                pobDao.updateByPrimaryKeySelective(bill);
            }
        }
        LadingBill lb = new LadingBill();
        lb.setId(record.getId());
        lb.setBusinessId(businessId);
        dataDao.updateByPrimaryKeySelective(lb); // 更新业员ID
        return record.getId(); // 返回ID
    }


    /***
     *  订单发货
     * @param record
     * @param isForce
     * @return
     */
    public Object send(LadingBillVo record, Boolean isForce) {
        if (record.getBillIds() == null || "".equals(record.getBillIds())) {
            return "请选择批号发货!";
        }
        if (BillType.CAR_ID.getIndex().equals(record.getType())) {
            String[] billIds = record.getBillIds().split(",");
            if (billIds.length != 1) {
                return "车号类型发货单，只能选择一个收货批号";
            }
        }
        record.setNo(Constants.generateServiceNO("T", Constants.generateLimitNumberStr(getMaxInNoOrder() + 1, 4)));
        if (isForce) {
            record.setActual(record.getNumberThisTime());
            record.setCheckStatus("1"); //
        }
        String orderId = record.getOrderIds().split(",")[0];
        Order order_ = orderDao.selectByPrimaryKey(Integer.valueOf(orderId));
//        record.setClientele(order_.getClienteleName());
        record.setSaler(order_.getSaleName()); // 操作员
        Integer id = dataDao.insertSelective(record); //创建提货单

        String[] orders = record.getOrderIds().split(",");
        String[] numbers = record.getOrderNumbers().split(",");
        String[] billIds = record.getBillIds().split(",");
        for (int i = 0; i < orders.length; i++) {
            BillBill bb = new BillBill();
            bb.setReceiveBillId(billIds[i]);
        }

        List<PurchaseOrderBill> pobList = new ArrayList<PurchaseOrderBill>();
        List<LadingOrder> loList = updateOrderIterator(isForce, orders, numbers, record, order_.getGoodsId(), order_.getActualPrice());
        int ladingOrders = ladingOrderDao.addBatch(loList), pointer = 0;
        if (record.getOrderIds() != null) {
            String[] sendIds = record.getBillIds().split(",");
            String[] sendNumbers = record.getBillNumbers().split(",");
            List<BillBill> bbList = new ArrayList<BillBill>();
            for (int i = 0; i < ladingOrders; i++) {
                BillBill bb = new BillBill();
                LadingOrder lo = loList.get(i);
                bb.setBillId(String.valueOf(lo.getId()));
                if (lo.getNumber().compareTo(BigDecimal.valueOf(Double.valueOf(sendNumbers[i]))) == -1) {
                    bb.setReceiveBillId((sendIds[pointer])); //
                    sendNumbers[i] = String.valueOf(BigDecimal.valueOf(Double.valueOf(sendNumbers[pointer])).subtract(lo.getNumber()));
                    bb.setNumber(lo.getNumber());
                    bbList.add(bb);
                } else if (lo.getNumber().compareTo(BigDecimal.valueOf(Double.valueOf(sendNumbers[i]))) == 1) {
                    int next = getNextSatisfied(sendNumbers, lo.getNumber().subtract(BigDecimal.valueOf(Double.valueOf(sendNumbers[pointer]))), pointer); //获取下一个满足当前订单余额的指针
                    BigDecimal total_ = lo.getNumber().subtract(BigDecimal.valueOf(Double.valueOf(sendNumbers[i])));
                    for (int j = pointer; j < next; j++) { //
                        BillBill bb1 = new BillBill();
                        total_ = total_.subtract(BigDecimal.valueOf(Double.valueOf(sendNumbers[j]))); // 从余额中扣减
                        bb1.setBillId(String.valueOf(lo.getId()));//
                        bb1.setReceiveBillId(String.valueOf(sendIds[i]));
                        bb1.setNumber(BigDecimal.valueOf(Double.valueOf(sendNumbers[i])));
                        bbList.add(bb1);
                        updatePurchaseOrderBill(sendIds, sendNumbers, j, record.getType(), record.getCarId());
                    }
                    pointer = next;
                    sendNumbers[pointer] = String.valueOf(BigDecimal.valueOf(Double.valueOf(sendNumbers[next])).subtract(total_));
                    bb.setReceiveBillId(String.valueOf(sendIds[pointer]));
                    bbList.add(bb);
                } else {
                    bb.setReceiveBillId(String.valueOf(sendIds[pointer])); //
                    sendNumbers[i] = String.valueOf(BigDecimal.valueOf(Double.valueOf(sendNumbers[pointer])).subtract(lo.getNumber()));
                    bb.setNumber(lo.getNumber());
                    bbList.add(bb);
                    updatePurchaseOrderBill(sendIds, sendNumbers, pointer, record.getType(), record.getCarId());
                    pointer++;
                }
            }
            bbDao.addBatch(bbList);
            ////批量更新收货单
        }
        return id;
    }

    @Transactional
    private void updatePurchaseOrderBill(String[] sendIds, String[] sendNumbers, int pointer, String type, String com) {
        PurchaseOrderBill pob1 = new PurchaseOrderBill();
        PurchaseOrderBill pob = pobDao.selectByPrimaryKey(Integer.valueOf(sendIds[pointer]));
        pob1.setId(Integer.valueOf(sendIds[pointer]));

        if (BillType.CAR_ID.getIndex().equals(type)) {
            pob1.setCom(com);
            pob1.setNumberSended(BigDecimal.valueOf(Double.valueOf(sendNumbers[pointer]))); //
        } else {
            pob1.setNumberSended(pob.getNumberSended().add(BigDecimal.valueOf(Double.valueOf(sendNumbers[pointer]))));
        }
        pobDao.updateByPrimaryKeySelective(pob1);

    }

    private int getNextSatisfied(String[] payCash, BigDecimal total, int pointer) {
        int next = 0;
        return iOrderAdvanceReceiptService.getNext(next, pointer, payCash, total);
    }


    /***
     * 更新订单迭代器
     */
    @Transactional
    private List<LadingOrder> updateOrderIterator(boolean isForce, String[] orders, String[] numbers, LadingBill record,
                                                  String goodsId, BigDecimal price) {
        List<LadingOrder> loList = new ArrayList<LadingOrder>();
        for (int i = 0; i < orders.length; i++) {
            LadingOrder lo = new LadingOrder();
            lo.setNumber(BigDecimal.valueOf(Double.valueOf(numbers[i])));
            if (isForce) {
                lo.setActual(BigDecimal.valueOf(Double.valueOf(numbers[i])));
            }
            lo.setOrderId(orders[i]);
            lo.setLadingId(String.valueOf(record.getId()));
            lo.setGoodsId(goodsId);
//            lo.setPrice(record.getP);
            Goods g = goodsDao.selectByPrimaryKey(Integer.valueOf(goodsId));
            lo.setPrice(price);
            lo.setTaxRatio(BigDecimal.valueOf(g.getTaxRatio()));
            lo.setLadingNo(record.getNo());
            loList.add(lo);
            Order order = new Order();
            order.setId(Integer.valueOf(orders[i]));
            Order res_order = orderDao.selectByPrimaryKey(Integer.valueOf(orders[i]));

            order.setDeliverNumber(BigDecimal.valueOf(Double.valueOf(numbers[i])).add(res_order.getDeliverNumber()));
            orderDao.updateByPrimaryKeySelective(order);
        }
        return loList;
    }

    /***
     * 创建提货订单：此方法只为后台用户创建提单使用
     * @param record
     * @return
     */
    @Override
    public synchronized Object createBySp(LadingBill record) {

        record.setNo(Constants.generateServiceNO("T", Constants.generateLimitNumberStr(getMaxInNoOrder() + 1, 4)));
        return dataDao.insertSelective(record);
    }


    private int getMaxInNoOrder() {
        String str = dataDao.queryCurrentDayMaxNo();
        if (str == null) {
            return 0;
        } else {
            String number = str.split("-")[1];
            return Integer.valueOf(number);
        }
    }

    @Override
    public synchronized Object deleteWithAuth(LadingBill record, Boolean isAuth) {
        LadingBill lb = dataDao.selectByPrimaryKey(record.getId());
        if (lb.getActual().compareTo(BigDecimal.valueOf(0.0)) == 1) {
            return "提单已填实体数，请先行清零再删除!";
        }
        List<LadingOrder> list = ladingOrderDao.selectByLadingId(String.valueOf(record.getId()));
        for (int i = 0; i < list.size(); i++) {
            LadingOrder lo = list.get(i);
            Order order = orderDao.selectByPrimaryKey(Integer.valueOf(lo.getOrderId()));
            Order order_ = new Order();
            order_.setId(order.getId());
            order_.setDeliverNumber(order.getDeliverNumber().subtract(lo.getNumber()));
            PurchaseOrderBill pob = new PurchaseOrderBill();
            pob.setId(Integer.valueOf(lo.getBillId()));
            PurchaseOrderBill pob_ = pobDao.selectByPrimaryKey(pob.getId());
            pob.setNumberSending(pob_.getNumberSending().subtract(lo.getNumber()));//
            pobDao.updateByPrimaryKeySelective(pob);
            orderDao.updateByPrimaryKeySelective(order_);
            ladingOrderDao.deleteByPrimaryKey(lo.getId());
        }
        return dataDao.deleteByPrimaryKey(record.getId());
    }

    @Override
    public synchronized Object checkSpLadingBill(LadingBill record) {
        LadingBill lb = dataDao.selectByPrimaryKey(record.getId());
        if (lb == null) {
            return "没有该提单参数相关数据，参数非法!";
        }
        if ("1".equals(record.getCheckStatus())) {
            Order order = new Order();
//            order.setId(Integer.valueOf(record./getOrderId()));
            Order res_order = orderDao.selectByPrimaryKey(order.getId());
            if ((res_order.getDeliverNumber().add(record.getNumberThisTime())).compareTo(res_order.getNumber()) == 0) {
                order.setDeliverStatus("1");
            } else if (res_order.getDeliverNumber().add(record.getNumberThisTime()).compareTo(res_order.getNumber()) == 1) {
                order.setDeliverStatus("2");
            }
            record.setCheckStatus("1"); //后台操作直接审核通过
//            扣减报价交易中数量
            order.setDeliverNumber(record.getNumberThisTime().add(res_order.getDeliverNumber()));
            orderDao.updateByPrimaryKeySelective(order);
        }
        return dataDao.updateByPrimaryKeySelective(record);
    }

    @Override
    public LadingBill selectByPrimaryKey(Integer id) {
        return dataDao.selectByPrimaryKey(id);
    }

    @Override
    public int updateByPrimaryKeySelective(LadingBill record) {
        return dataDao.updateByPrimaryKeySelective(record);
    }

    /**
     * 变更
     *
     * @param record
     * @return
     */
    @Override
    public Object update(LadingBill record) {
        LadingBill lb = dataDao.selectByPrimaryKey(record.getId());
        if (lb == null) return "提单不存在，数据错误";
        return dataDao.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateByPrimaryKey(LadingBill record) {
        return dataDao.updateByPrimaryKey(record);
    }

    @Override
    public List<LadingBill> queryByPage(LadingBillVo arg) {
        return dataDao.queryByPage(arg);
    }

    @Override
    public List<LadingBillVo> combineQueryByPage(LadingBillVo arg) {
        return dataDao.combineQueryByPage(arg);
    }

    @Override
    public int queryCount(LadingBillVo arg) {
        return dataDao.queryCount(arg);
    }

    @Override
    public Object update_labing_bill_actual(LadingOrder arg) {
        LadingOrder se_res = ladingOrderDao.selectByPrimaryKey(arg.getId());
        if (se_res.getActual().compareTo(BigDecimal.valueOf(0.0)) == 1) {
            return "提货单已经关闭，不能修改提货单!";
        }
        Order o = orderService.selectByPrimaryKey(Integer.valueOf(se_res.getOrderId()));
        if (!"0".equals(o.getStatus())) {
            return "订单已关闭,不能增加实提数量!";
        }
        arg.setActual(arg.getActual().add(se_res.getActual()));
        int service_res = ladingOrderDao.updateByPrimaryKeySelective(arg);
        if (service_res > 0) {
            Order order = new Order();
            order.setActualNumber(arg.getActual());
            order.setId(Integer.valueOf(se_res.getOrderId()));
            order.setNumber(se_res.getNumber().subtract(arg.getActual()));
            Object obj = orderService.addActualNumber(order);
            if (obj instanceof Integer) {
                int res = Integer.valueOf(obj.toString());
                if (res == 0) {
                    throw new Error("修改实提数量错误");
                }
            }
        }
        LadingBill ladingBill = new LadingBill();
        LadingBill lb = dataDao.selectByPrimaryKey(Integer.valueOf(se_res.getLadingId()));
        ladingBill.setId(lb.getId());
        ladingBill.setActual(arg.getActual().add(lb.getActual()));
        dataDao.updateByPrimaryKeySelective(ladingBill);
        return service_res;
    }

    /**
     * 此方法3期开始废弃
     *
     * @param arg
     * @param userId
     * @return
     */
    @Transactional
    @Override
    @Deprecated
    public Object batchUpdateLadingBillActual(LadingOrderVo arg, String userId) {
        if (arg.getIds() == null || "".equals(arg.getIds())) {
            return "操作非法!";
        }
        String[] ids = arg.getIds().split(",");
        String[] actuals = arg.getActuals().split(",");
        BigDecimal total = BigDecimal.valueOf(0.0);
        String lbId = "";
        Map<String, PurchaseOrderBill> pobMap = new HashMap<String, PurchaseOrderBill>();
        for (int i = 0; i < ids.length; i++) {
            LadingOrder se_res = ladingOrderDao.selectByPrimaryKey(Integer.valueOf(ids[i]));
            lbId = se_res.getLadingId();
            LadingOrder ladingOrder = new LadingOrder();
            ladingOrder.setId(se_res.getId());
            ladingOrder.setActual(BigDecimal.valueOf(Double.valueOf(actuals[i])));
            total = total.add(ladingOrder.getActual());
            PurchaseOrderBill purchaseOrderBill1 = pobDao.selectByPrimaryKey(Integer.valueOf(se_res.getBillId()));
            PurchaseOrderBill purchaseOrderBill = new PurchaseOrderBill();
            purchaseOrderBill.setId(purchaseOrderBill1.getId());
            //
            purchaseOrderBill.setNumberSending(purchaseOrderBill1.getNumberSending().subtract(se_res.getNumber()));
            purchaseOrderBill.setNumberSended(purchaseOrderBill1.getNumberSended().add(ladingOrder.getActual()));
            if (purchaseOrderBill.getNumberSending().compareTo(BigDecimal.valueOf(0.0)) == -1
                    || purchaseOrderBill.getNumberSended().compareTo(BigDecimal.valueOf(0.0)) == -1) {
                System.out.println("抛出异常!");
                throw new RuntimeException("数据有误，入库失败");
            }
            ladingOrderDao.updateByPrimaryKeySelective(ladingOrder);
            int update = pobDao.updateByPrimaryKeySelective(purchaseOrderBill);
            if (update > 0 && "0".equals(purchaseOrderBill1.getType())) { // 车号类型发货单
//                PurchaseOrder po = poDao.selectByPrimaryKey(Integer.valueOf(purchaseOrderBill1.getOrderId()));
                PurchaseOrderBill pob2 = pobMap.get(String.valueOf(purchaseOrderBill.getId()));
                if (pob2 != null) {
                    pob2.setNumberReceive(pob2.getNumberReceive().add(ladingOrder.getActual()));
                    pobMap.put(String.valueOf(purchaseOrderBill.getId()), pob2);
                } else {
                    PurchaseOrderBill purchaseOrderBill2 = new PurchaseOrderBill();
                    purchaseOrderBill2.setId(purchaseOrderBill.getId());
                    purchaseOrderBill2.setNumberReceive(ladingOrder.getActual());
                    purchaseOrderBill2.setReceiverId(userId);
                    pobMap.put(String.valueOf(purchaseOrderBill2.getId()), purchaseOrderBill2);
                }
            }
            Order o = orderService.selectByPrimaryKey(Integer.valueOf(se_res.getOrderId()));
            if (!"0".equals(o.getStatus())) {
                throw new RuntimeException("订单已关闭,不能增加实提数量!");
            }
            Order order = new Order();
            order.setActualNumber(ladingOrder.getActual());
            order.setId(o.getId());
            order.setNumber(se_res.getNumber().subtract(ladingOrder.getActual()));
            Object obj = orderService.addActualNumber(order);
            if (obj instanceof Integer) {
                int res = Integer.valueOf(obj.toString());
                if (res == 0) {
                    throw new RuntimeException("修改实提数量错误");
                }
            }
            LadingBill ladingBill = new LadingBill();
            LadingBill lb = dataDao.selectByPrimaryKey(Integer.valueOf(se_res.getLadingId()));
            ladingBill.setId(lb.getId());
            ladingBill.setActual(ladingOrder.getActual().add(lb.getActual()));
            dataDao.updateByPrimaryKeySelective(ladingBill);
        }
        for (PurchaseOrderBill key : pobMap.values()) {
            pobService.instore(key);
        }
        LadingBill lb = new LadingBill();
        lb.setId(Integer.valueOf(lbId));
        lb.setActual(total);
        dataDao.updateByPrimaryKeySelective(lb);
        return lb.getId();
    }

    public void instoreBySingle() {

    }

    public LadingOrder instoreLadingOrder(Integer id, BigDecimal actual) {
        LadingOrder ladingOrder = ladingOrderDao.selectByPrimaryKey(id);
        if (ladingOrder == null || (ladingOrder.getActual().compareTo(BigDecimal.ZERO) != 0)) {
            throw new RuntimeException("数据异常");
        }
        LadingOrder lo = new LadingOrder();
        lo.setId(id);
        lo.setActual(actual);
        ladingOrderDao.updateByPrimaryKeySelective(lo);
        return ladingOrder;
    }

    @Transactional
    @Override
    public Object batchUpdateLadingBillActual2(LadingOrderVo arg, String userId) {
        if (arg.getIds() == null || "".equals(arg.getIds())) {
            return "操作非法!";
        }
        String[] ids = arg.getIds().split(",");
        String[] actuals = arg.getActuals().split(",");
        BigDecimal total = BigDecimal.valueOf(0.0);
        String lbId = "";
        Map<String, PurchaseOrderBill> pobMap = new HashMap<String, PurchaseOrderBill>();
        for (int i = 0; i < ids.length; i++) {
            BigDecimal actual = BigDecimal.valueOf(Double.valueOf(actuals[i]));
            LadingOrder lo = instoreLadingOrder(Integer.valueOf(ids[i]), actual);
            total = total.add(actual);
            lbId = String.valueOf(lo.getId());//
            PurchaseOrderBill purchaseOrderBill = pobService.changeNumber(Integer.valueOf(lo.getBillId()),
                    BigDecimal.ZERO, actual, lo.getNumber().negate(), null);
            if ("0".equals(purchaseOrderBill.getType())) { // 车号类型发收货单
                PurchaseOrderBill pob2 = pobMap.get(String.valueOf(purchaseOrderBill.getId()));
                if (pob2 != null) {
                    pob2.setNumberReceive(pob2.getNumberReceive().add(actual));
                    pobMap.put(String.valueOf(purchaseOrderBill.getId()), pob2);
                } else {
                    PurchaseOrderBill purchaseOrderBill2 = new PurchaseOrderBill();
                    purchaseOrderBill2.setId(purchaseOrderBill.getId());
                    purchaseOrderBill2.setNumberReceive(actual);
                    purchaseOrderBill2.setReceiverId(userId);
                    pobMap.put(String.valueOf(purchaseOrderBill2.getId()), purchaseOrderBill2); //
                }
            }
            Order o = orderService.selectByPrimaryKey(Integer.valueOf(lo.getOrderId()));
            if (!"0".equals(o.getStatus())) {
                throw new RuntimeException("订单已关闭,不能增加实提数量!");
            }
            Order order = new Order();
            order.setActualNumber(actual);
            order.setId(o.getId());
            order.setNumber(lo.getNumber().subtract(actual));
            Object obj = orderService.addActualNumber(order);
            if (obj instanceof Integer) {
                int res = Integer.valueOf(obj.toString());
                if (res == 0) {
                    throw new RuntimeException("修改实提数量错误");
                }
            }
            LadingBill ladingBill = new LadingBill();
            LadingBill lb = dataDao.selectByPrimaryKey(Integer.valueOf(lo.getLadingId()));
            ladingBill.setId(lb.getId());
            ladingBill.setActual(actual.add(lb.getActual()));
            dataDao.updateByPrimaryKeySelective(ladingBill);
        }
        for (PurchaseOrderBill key : pobMap.values()) {
            pobService.instore(key);
        }
        LadingBill lb = new LadingBill();
        lb.setId(Integer.valueOf(lbId));
        lb.setActual(total);
        dataDao.updateByPrimaryKeySelective(lb);
        return lb.getId();
    }


    @Override
    public int selectByStoreId(LadingBill record) {
        return dataDao.selectByStoreId(record);
    }

    @Override
    public int applyPaper(LadingBill record) {
        LadingBill record1 = new LadingBill();
        record1.setPaperStatus("1");


        record1.setId(record.getId());
        return dataDao.updateByPrimaryKeySelective(record1);
    }

    @Transactional
    @Override
    public synchronized Object clear(LadingBillVo record, UserVo user) {
        LadingBill lb = dataDao.selectByPrimaryKey(record.getId());
        if (lb.getActual().compareTo(BigDecimal.valueOf(0.0)) == 0) {
            return "非法操作：提货单尚未录入实提数量";
        }
        List<LadingOrder> list = ladingOrderDao.selectByLadingId(String.valueOf(record.getId()));
        Map<String, Order> ordersMap = new HashMap<String, Order>();
        Map<String, PurchaseOrderBill> takeOverMap = new HashMap<String, PurchaseOrderBill>();
        for (int i = 0; i < list.size(); i++) {
            LadingOrder lo = list.get(i);
            PurchaseOrderBill pob = null;
            Order order = null;
            if (ordersMap.get(lo.getOrderId()) == null) {
                order = new Order();
                order.setId(Integer.valueOf(lo.getOrderId()));
                order.setNumber(lo.getNumber());
                order.setActualNumber(lo.getActual());
            } else {
                order = ordersMap.get(lo.getOrderId());
                order.setActualNumber(order.getActualNumber().add(lo.getActual()));
                order.setNumber(order.getNumber().add(lo.getNumber()));
            }
            ordersMap.put(String.valueOf(order.getId()), order);
            if (takeOverMap.get(lo.getBillId()) == null) {
                pob = new PurchaseOrderBill();
                pob.setId(Integer.valueOf(lo.getBillId()));
                pob.setNumber(lo.getNumber());
                pob.setNumberReceive(lo.getActual());
            } else {
                pob = takeOverMap.get(lo.getBillId());
                pob.setId(Integer.valueOf(lo.getBillId()));
                pob.setNumberReceive(pob.getNumber().add(lo.getActual()));// 中文
                pob.setNumber(pob.getNumber().add(lo.getNumber()));
            }
            takeOverMap.put(lo.getBillId(), pob);
            lo.setActual(BigDecimal.valueOf(0.0));//
            ladingOrderDao.updateByPrimaryKeySelective(lo);
        }

        for (String in : ordersMap.keySet()) {
            Order order = ordersMap.get(in);//得到每个key多对用value的值
            Order order1 = orderService.selectByPrimaryKey(order.getId());
            BigDecimal canSend = BigDecimal.valueOf(0.0);
            canSend = order1.getDeliverNumber();
            canSend = order1.getNumber().subtract(canSend);
            BigDecimal remain = order.getNumber().subtract(order.getActualNumber());
            if (remain.compareTo(canSend) == 1) {
                throw new RuntimeException("订单可发货数量小于销售提货单未提货数量，不能清零");
            }
            if (!order1.getStatus().equals("0")) {
                boolean isAuth = false;
                for (int i = 0; i < user.getPermissions().size(); i++) {
                    Permission per = user.getPermissions().get(i);
                    if (per.getId() == 138) {
                        isAuth = true;
                    }
                }
                if (isAuth) {
                    if (order1.getStatus().equals("2")) { // 强制执行完毕，
                        order1.getOfferId();
                        Offer offer = offerDao.selectByPrimaryKey(Integer.valueOf(order1.getOfferId()));
                        Offer offer_ = new Offer();
                        offer_.setId(offer.getId());
                        BigDecimal remain_ = BigDecimal.valueOf(0.0);
                        remain_ = order1.getNumber().subtract(order1.getActualNumber());
                        offer_.setSaleNum(BigDecimal.valueOf(offer.getSaleNum()).subtract(remain_).doubleValue());
                        offer_.setWithholdingNum(BigDecimal.valueOf(offer.getWithholdingNum()).add(remain_).doubleValue());
                        offerDao.updateByPrimaryKeySelective(offer_); // 处理报价数据
                    }
                } else {
                    throw new RuntimeException("订单执行完毕订单不能清零,请申请授权执行");
                }
            }
            if (order1.getStatus().equals("2")) {
                order.setDeliverNumber(order1.getDeliverNumber().subtract(order.getActualNumber()).add(order.getNumber())); // 强制执行完毕的销售订单，已发货数量应该累计提单数量
            } else {
                order.setDeliverNumber(order1.getDeliverNumber().add(order.getNumber().subtract(order.getActualNumber()))); // 修复清零时，发货数量变成清零提单数量
            }
            order.setStatus("0"); // 订单恢复执行中
            order.setActualNumber(order1.getActualNumber().subtract(order.getActualNumber()));
            if (order1.getStatus().equals("2") || order1.getStatus().equals("3")) { // 强制执行完成或者执行完成时的销售订单清零，必须返还销售佣金
                boolean resBack = backCommission(order1);
                if (!resBack) {
                    throw new RuntimeException("佣金账户退款失败!");
                }
            }
            order.setNumber(null);
            orderService.updateByPrimaryKeySelective(order);
        }
        for (String in : takeOverMap.keySet()) {
            PurchaseOrderBill bill = takeOverMap.get(in);//得到每个key多对用value的值
            PurchaseOrderBill bill1 = pobDao.selectByPrimaryKey(bill.getId());
            // 更新数据，状态
            if ("0".equals(bill1.getType())) { // 车号类型收货单，只能和一个提单匹配，但可以和一个提单中的多个订单匹配
                PurchaseOrder billOrder = poDao.selectByPrimaryKey(Integer.valueOf(bill1.getOrderId()));
                if ("3".equals(billOrder.getStatus())) {
                    throw new RuntimeException("采购订单已经强制执行完毕，不能清零!");
                }
                BigDecimal canReceive = BigDecimal.valueOf(0.0);
                canReceive = billOrder.getNumberActualReceive().add(billOrder.getNumberReceiving());
                canReceive = billOrder.getNumber().subtract(canReceive);
                BigDecimal unReceived = BigDecimal.valueOf(0.0);
                unReceived = bill1.getNumber().subtract(bill1.getNumberReceive());//
                if (unReceived.compareTo(canReceive) == 1) {
                    throw new RuntimeException("采购订单可收货数量小于收货单数量，不能清零!");
                }
                billOrder.setNumberReceiving(billOrder.getNumberReceiving().add(bill1.getNumber()));//
                billOrder.setNumberActualReceive(billOrder.getNumberActualReceive().subtract(bill1.getNumberSended()));
                billOrder.setStatus("1"); // 采购订单执行中
                poDao.updateByPrimaryKeySelective(billOrder); // 更新采购订单
                bill1.setNumberReceive(BigDecimal.valueOf(0.0)); //
                bill1.setNumberSending(bill.getNumber());// b
                bill1.setNumberSended(BigDecimal.valueOf(0.0)); //修正提单清零时，已发货数量为0的错误
                pobDao.updateByPrimaryKeySelective(bill1); // 更新收货单数据
            } else if ("2".equals(bill1.getType())) { //介绍信 --，可以和多个提单匹配
                if (bill1.getNumberReceive().compareTo(BigDecimal.valueOf(0.0)) == 1) { //
                    throw new RuntimeException("介绍信已填实收数，不能清零");
                }
                bill1.setNumberSending(bill1.getNumberSending().add(bill.getNumber())); // 修复介绍信类型收货单清零后，发货中数量没有恢复
                bill1.setNumberSended(bill1.getNumberSended().subtract(bill.getNumberReceive())); // 清除与本次提单匹配部分
                pobDao.updateByPrimaryKeySelective(bill1);
            } else { //  转货权，可以和多个提单匹配
                bill1.setNumberSending(bill1.getNumberSending().add(bill.getNumber()));
                bill1.setNumberSended(bill1.getNumberSended().subtract(bill.getNumberReceive()));
                bill1.setStatus("1"); //收货单执行中
                pobDao.updateByPrimaryKeySelective(bill1); // 更新收货单数据
            }
        }
        record.setActual(BigDecimal.valueOf(0.0));
        return dataDao.updateByPrimaryKeySelective(record);
    }


    /***
     *  从销售员账户中返还销售佣金
     * @param order 销售订单
     * @return
     */
    @Transactional
    public boolean backCommission(Order order) {
        SaleCommission sc = new SaleCommission();
        sc.setOrderId(String.valueOf(order.getId()));
        sc = saleCommissionDao.selectOneByOrderId(sc);
        if (sc.getId() == null) return false; //
        sc.setStatus("0"); // 发放中
        SalePersonAccount spa = spaDao.selectBySaleID(sc.getSaleId());
        if (spa == null) return false;
        BigDecimal bd = order.getNumber().multiply(sc.getPercent());
        spa.setCashWillReceiveTotal(spa.getCashWillReceiveTotal().add(bd)); //回退到未到账佣金
        spa.setCashCanWithDrawTotal(spa.getCashCanWithDrawTotal().subtract(sc.getCommission())); // 从可提现佣金中扣减
        spa.setCashTotal(spa.getCashTotal().subtract(sc.getCommission())); // 从历史累计提现佣金中扣减
        int res = spaDao.updateByPrimaryKeySelective(spa);
        if (order.getStatus().equals("2")) { //  强制执行完毕的订单返佣金额按订单数量进行复原
            sc.setCommission(bd);
        }
        int resUpdateSC = saleCommissionDao.updateByPrimaryKeySelective(sc);
        if (res == 1 && resUpdateSC == 1) return true;
        return false;
    }

    @Transactional
    @Override
    public Object replace(LadingOrder record) {
        LadingOrder lo = ladingOrderDao.selectByPrimaryKey(record.getId());
        if (lo.getBillId().equals(record.getBillId())) {
            return "所选批号相同，不能替换";
        }
        PurchaseOrderBill pob = pobDao.selectByPrimaryKey(Integer.valueOf(lo.getBillId()));

        PurchaseOrderBill pob1 = pobDao.selectByPrimaryKey(Integer.valueOf(record.getBillId()));
        if (!pob1.getStoreId().equals(pob.getStoreId())) {
            Store replaced = storeDao.selectByPrimaryKey(Integer.valueOf(pob.getStoreId()));
            Store newStore = storeDao.selectByPrimaryKey(Integer.valueOf(pob1.getStoreId()));
            if ("1".equals(newStore.getShowDriver()) && "0".equals(replaced.getShowDriver())) {
                return "不需要司机信息的仓库不能使用需要司机信息的仓库仓库替换";
            }
        }


//        if(pob1.get)

        if (!pob.getGoodsId().equals(pob1.getGoodsId())) {
            return "请选择同一种产品进行替换";
        }
        if ("0".equals(pob1.getType())) { //车号
            if (lo.getNumber().compareTo(pob1.getNumber()) == 1) {
                return "车号类型收货单库存不足";
            }
        } else if ("2".equals(pob1.getType())) { //或介绍信
            if (lo.getNumber().compareTo(pob1.getNumber().subtract(pob1.getNumberSended().add(pob1.getNumberSending()))) == 1) {
                return "介绍信类型收货单库存不足";
            }
        } else if ("1".equals(pob1.getType())) { //或转货权
            if (lo.getNumber().compareTo(pob1.getNumberReceive().subtract(pob1.getNumberSended().add(pob1.getNumberSending()))) == 1) {
                return "转货权类型收货单库存不足";
            }
        }
        pob.setNumberSending(pob.getNumberSending().subtract(lo.getNumber()));
        pobDao.updateByPrimaryKeySelective(pob);
        pob1.setNumberSending(pob1.getNumberSending().add(lo.getNumber()));
        pobDao.updateByPrimaryKeySelective(pob1);
        record.setBillBatch(pob1.getBatchNum());
        record.setBillId(String.valueOf(pob1.getId()));
        ladingOrderDao.updateByPrimaryKeySelective(record);
        LadingBill lb = new LadingBill();
        lb.setStoreId(pob1.getStoreId());
        lb.setStoreName(pob1.getStoreName());
        lb.setId(Integer.valueOf(lo.getLadingId()));
        return dataDao.updateByPrimaryKeySelective(lb);

    }


}
